package fun.cyhgraph.service.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import fun.cyhgraph.common.ErrorCode;
import fun.cyhgraph.constant.MessageConstant;
import fun.cyhgraph.constant.StatusConstant;
import fun.cyhgraph.exception.BusinessException;
import fun.cyhgraph.exception.ThrowUtils;
import fun.cyhgraph.mapper.CategoryMapper;
import fun.cyhgraph.model.dto.SetmealDTO;
import fun.cyhgraph.model.dto.SetmealPageDTO;
import fun.cyhgraph.model.entity.*;
import fun.cyhgraph.exception.DeleteNotAllowedException;
import fun.cyhgraph.mapper.SetmealDishMapper;
import fun.cyhgraph.mapper.SetmealMapper;
import fun.cyhgraph.model.merchantDto.SetmealMerchantDTO;
import fun.cyhgraph.model.merchantDto.SetmealPageMerchantDTO;
import fun.cyhgraph.result.PageResult;
import fun.cyhgraph.service.CategoryService;
import fun.cyhgraph.service.DishService;
import fun.cyhgraph.service.SetmealService;
import fun.cyhgraph.model.vo.DishItemVO;
import fun.cyhgraph.model.vo.SetmealVO;
import fun.cyhgraph.model.vo.SetmealWithPicVO;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class SetmealServiceImpl extends ServiceImpl< SetmealMapper,  Setmeal> implements  SetmealService {

    @Resource
    private SetmealMapper setmealMapper;
    @Resource
    private SetmealDishMapper setmealDishMapper;
    @Resource
    private DishService dishService;

    /**
     * 新增套餐
     * @param setmealDTO
     */
    @Transactional(rollbackFor = Exception.class)
    public void addSetmeal(SetmealMerchantDTO setmealDTO) {
        // 检查套餐名称是否已存在
        String setName = setmealDTO.getName();
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Setmeal::getName, setName)
                .eq(Setmeal::getMerchantId, setmealDTO.getMerchantId());
        Setmeal existingSetmeal = setmealMapper.selectOne(queryWrapper);
        if (existingSetmeal != null) {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR , "套餐名称已存在，请更换名称后重试！");
        }

        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        setmeal.setStatus(1);
        setmeal.setMerchantId(setmealDTO.getMerchantId());
        setmeal.setCreateUser(setmealDTO.getMerchantId());
        setmeal.setUpdateUser(setmealDTO.getMerchantId());
        setmeal.setCreateTime(LocalDateTime.now());
        setmeal.setUpdateTime(LocalDateTime.now());
        setmealMapper.addSetmeal(setmeal);
        // 套餐包含的菜品批量插入
        Integer setmealId = setmeal.getId();
        // 1. 遍历setmealDTO中的菜品列表，每个菜品都为其setmealId字段赋值
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        if (setmealDishes != null && !setmealDishes.isEmpty()) {
            setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmealId));
            //先校验菜品是否在售或者是否存在
            try {
                setmealDishMapper.insertBatch(setmealDishes);
            }catch (Exception e){
                throw new BusinessException(ErrorCode.FORBIDDEN_ERROR , "菜品状态有误或菜品信息，请检查后重试！");
            }

        }
    }

    /**
     * 套餐条件分页查询
     * @param setmealPageDTO
     * @return
     */
    public PageResult getPageList(SetmealPageMerchantDTO setmealPageDTO) {
        PageHelper.startPage(setmealPageDTO.getPage(), setmealPageDTO.getPageSize());
        Page<Setmeal> setmealList = setmealMapper.getPageList(setmealPageDTO);
        return new PageResult(setmealList.getTotal(), setmealList.getResult());
    }

    /**
     * 根据套餐id查询套餐，包括菜品信息
     * @param id
     * @return
     */
    public SetmealVO getSetmealById(Integer id , Integer merchantId) {
        Setmeal setmeal = setmealMapper.getSetmealById(id , merchantId);
        if (setmeal == null){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR , "找不到对应的套餐");
        }
        List<SetmealDish> setmealDishes = setmealDishMapper.getDishesBySetmealId(id);
        // 组成SetmealVO后返回
        SetmealVO setmealVO = new SetmealVO();
        BeanUtils.copyProperties(setmeal, setmealVO);
        setmealVO.setSetmealDishes(setmealDishes);
        return setmealVO;
    }

    /**
     * 起售停售套餐
     * @param id
     */
    public void onOff(Integer id , Integer merchantId) {
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Setmeal::getId, id)
                .eq(Setmeal::getMerchantId, merchantId);
        Setmeal setmeal = setmealMapper.getSetmealById(id , merchantId);
        if (setmeal == null){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR , "找不到对应的套餐");
        }
        if (setmeal.getStatus() == 0){
            setmeal.setStatus(1);
        }else if( setmeal.getStatus() == 1) {
            setmeal.setStatus(0);
        }else {
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR , "套餐状态有误");
        }
        int update = setmealMapper.update(setmeal, queryWrapper);
        if (update == 0){
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR , "修改失败");
        }
    }

    /**
     * 修改套餐
     * @param setmealDTO
     */
    public void update(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        // 先修改套餐setmeal
        setmealMapper.update(setmeal);
        // 再修改套餐下的菜品setmealDish
        // 由于行数据可能不同，因此需要先根据setmealId批量删除，再批量插入
        Integer setmealId = setmealDTO.getId();
        setmealDishMapper.deleteBySetmealId(setmealId);
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmealId));
        setmealDishMapper.insertBatch(setmealDishes);
    }

    /**
     * 批量删除套餐
     * @param ids
     */
    public void deleteBatch(List<Integer> ids , Integer merchantId) {
        // 遍历要删除的所有套餐，如果但凡有一个在起售就抛异常
        for(Integer id : ids){
            Setmeal setmeal = setmealMapper.getSetmealById(id , merchantId);
            if (setmeal.getStatus() == StatusConstant.ENABLE){
                throw new DeleteNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        }
        setmealMapper.deleteBatch(ids);
        setmealDishMapper.deleteBatch(ids);
    }

    /**
     * 根据分类id查询所有套餐
     * @return
     */
    public List<Setmeal> getList(Integer categoryId) {
        // 还有一个条件：起售的套餐才能展示在客户端
        Setmeal setmeal = new Setmeal();
        setmeal.setCategoryId(categoryId);
        setmeal.setStatus(StatusConstant.ENABLE);
        List<Setmeal> setmealList = setmealMapper.getList(setmeal);
        return setmealList;
    }

    /**
     * 根据套餐id查询所有菜品
     * @param id
     * @return
     */
    public List<DishItemVO> getSetmealDishesById(Integer id) {
        List<DishItemVO> dishItemVOList = setmealMapper.getSetmealDishesById(id);
        return dishItemVOList;
    }

    /**
     * 根据套餐id获取套餐详情，其中菜品都要有pic图片信息
     * @param id
     * @return
     */
    public SetmealWithPicVO getSetmealWithPic(Integer id , Integer merchantId) {
        Setmeal setmeal = setmealMapper.getSetmealById(id , merchantId);
        // 该套餐下的每个菜品都需要加上pic字段
        List<SetmealDishWithPic> dishWithPics = setmealDishMapper.getDishesWithPic(id);
        // 组成setmealWithPicVO后返回
        SetmealWithPicVO setmealWithPicVO = new SetmealWithPicVO();
        BeanUtils.copyProperties(setmeal, setmealWithPicVO);
        setmealWithPicVO.setSetmealDishes(dishWithPics);
        return setmealWithPicVO;
    }

}
